import os
import json
import time
import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext, simpledialog
import requests
from threading import Thread
import subprocess

class DeepSeekCodeGenerator:
    def __init__(self, root):
        self.root = root
        self.root.title("DeepSeek 代码生成与优化工具 v3.0")
        self.root.geometry("1100x850")
        
        # 初始化变量
        self.api_key = ""
        self.api_url = "https://api.deepseek.com/v1/chat/completions"
        self.config_file = "deepseek_config.json"
        self.is_running = False
        self.generated_code = ""
        self.existing_code = ""
        
        # 创建界面
        self.setup_ui()
        self.load_config()

    def setup_ui(self):
        """创建用户界面"""
        main_frame = ttk.Frame(self.root, padding=15)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # API配置区域
        api_frame = ttk.LabelFrame(main_frame, text="API 配置", padding=10)
        api_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(api_frame, text="API Key:").grid(row=0, column=0, sticky=tk.W)
        self.api_key_entry = ttk.Entry(api_frame, width=70, show="*")
        self.api_key_entry.grid(row=0, column=1, padx=5, sticky=tk.EW)
        ttk.Button(api_frame, text="保存配置", command=self.save_config).grid(row=0, column=2, padx=5)
        api_frame.columnconfigure(1, weight=1)

        # 代码需求区域
        input_frame = ttk.LabelFrame(main_frame, text="代码需求", padding=10)
        input_frame.pack(fill=tk.X, pady=5)
        
        self.requirement_entry = scrolledtext.ScrolledText(input_frame, height=8, wrap=tk.WORD)
        self.requirement_entry.pack(fill=tk.BOTH, expand=True)

        # 交互设置区域
        settings_frame = ttk.LabelFrame(main_frame, text="交互设置", padding=10)
        settings_frame.pack(fill=tk.X, pady=5)

        # 第一行设置
        settings_row1 = ttk.Frame(settings_frame)
        settings_row1.pack(fill=tk.X, pady=5)
        
        ttk.Label(settings_row1, text="优化轮次:").pack(side=tk.LEFT)
        self.rounds_spinbox = ttk.Spinbox(settings_row1, from_=1, to=10, width=5)
        self.rounds_spinbox.set(3)
        self.rounds_spinbox.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(settings_row1, text="编程语言:").pack(side=tk.LEFT, padx=10)
        self.language_combobox = ttk.Combobox(settings_row1, values=[
            "Python", "JavaScript", "Java", "C++", "C#", "Go", "Rust", "PHP", "Ruby", "Swift"
        ], width=12)
        self.language_combobox.set("Python")
        self.language_combobox.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(settings_row1, text="生成模式:").pack(side=tk.LEFT, padx=10)
        self.mode_combobox = ttk.Combobox(settings_row1, values=["稳定模式", "发散模式"], width=12)
        self.mode_combobox.set("稳定模式")
        self.mode_combobox.pack(side=tk.LEFT, padx=5)

        # 第二行设置 - 已有代码
        settings_row2 = ttk.Frame(settings_frame)
        settings_row2.pack(fill=tk.X, pady=5)
        
        ttk.Button(settings_row2, text="浏览代码文件", command=self.browse_existing_code).pack(side=tk.LEFT)
        self.existing_code_path = ttk.Entry(settings_row2)
        self.existing_code_path.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        ttk.Button(settings_row2, text="查看内容", command=self.show_code_content).pack(side=tk.LEFT, padx=5)

        # 操作按钮和保存区域
        action_frame = ttk.Frame(main_frame)
        action_frame.pack(fill=tk.X, pady=10)

        # 操作按钮组
        btn_group = ttk.Frame(action_frame)
        btn_group.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(btn_group, text="生成代码", command=self.start_generation_thread, width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_group, text="停止", command=self.stop_generation, width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_group, text="运行代码", command=self.run_saved_code, width=12).pack(side=tk.LEFT, padx=2)
        ttk.Button(btn_group, text="强制重试", command=self.force_retry, width=12).pack(side=tk.LEFT, padx=2)

        # 保存路径组
        save_group = ttk.Frame(action_frame)
        save_group.pack(side=tk.LEFT, padx=10, fill=tk.X, expand=True)
        
        ttk.Label(save_group, text="保存路径:").pack(side=tk.LEFT)
        self.save_path_entry = ttk.Entry(save_group)
        self.save_path_entry.pack(side=tk.LEFT, padx=5, fill=tk.X, expand=True)
        ttk.Button(save_group, text="浏览...", command=self.browse_save_path).pack(side=tk.LEFT, padx=2)
        ttk.Button(save_group, text="保存代码", command=self.save_code).pack(side=tk.LEFT, padx=2)

        # 状态标签
        self.save_status_label = ttk.Label(action_frame, text="", foreground="blue")
        self.save_status_label.pack(side=tk.LEFT, padx=10)

        # 日志显示区域
        log_frame = ttk.LabelFrame(main_frame, text="交互日志", padding=10)
        log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.log_text = scrolledtext.ScrolledText(log_frame, wrap=tk.WORD)
        self.log_text.pack(fill=tk.BOTH, expand=True)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(fill=tk.X, pady=(5,0))

    # 核心功能方法
    def browse_existing_code(self):
        filetypes = [
            ("代码文件", "*.py;*.js;*.java;*.cpp;*.cs;*.go;*.rs;*.php;*.rb;*.swift"),
            ("所有文件", "*.*")
        ]
        
        filepath = filedialog.askopenfilename(filetypes=filetypes)
        if filepath:
            try:
                # 尝试UTF-8编码
                with open(filepath, "r", encoding="utf-8") as f:
                    self.existing_code = f.read()
                
                self.existing_code_path.delete(0, tk.END)
                self.existing_code_path.insert(0, filepath)
                
                # 显示加载信息
                file_size = os.path.getsize(filepath) / 1024
                self.log_message(f"\n✓ 已加载: {os.path.basename(filepath)} ({file_size:.1f}KB)")
                self.status_var.set(f"已加载: {os.path.basename(filepath)}")
                
                # 自动填充需求框
                if not self.requirement_entry.get("1.0", tk.END).strip():
                    self.requirement_entry.insert(tk.END, f"优化以下{self.language_combobox.get()}代码:")
                
            except UnicodeDecodeError:
                try:
                    with open(filepath, "r", encoding="gbk") as f:
                        self.existing_code = f.read()
                    self.log_message(f"\n✓ 已加载(GBK编码): {os.path.basename(filepath)}")
                except Exception as e:
                    self.log_message(f"\n! 加载失败: {str(e)}")
                    self.existing_code = ""
            except Exception as e:
                self.log_message(f"\n! 错误: {str(e)}")
                self.existing_code = ""

    def show_code_content(self):
        if not self.existing_code:
            messagebox.showwarning("警告", "没有可显示的代码内容")
            return
        
        preview = self.existing_code[:500] + ("..." if len(self.existing_code) > 500 else "")
        messagebox.showinfo("代码预览", f"前500字符预览:\n\n{preview}")

    def start_generation_thread(self):
        if not self.api_key:
            messagebox.showerror("错误", "API Key不能为空")
            return
        
        if not self.existing_code:
            messagebox.showwarning("警告", "请先上传要优化的代码文件")
            return
        
        requirement = self.requirement_entry.get("1.0", tk.END).strip()
        if not requirement:
            messagebox.showinfo("提示", "请描述优化需求")
            return
        
        self.is_running = True
        Thread(target=self.generate_and_optimize_code, args=(requirement,), daemon=True).start()

    def generate_and_optimize_code(self, requirement):
        try:
            language = self.language_combobox.get()
            rounds = int(self.rounds_spinbox.get())
            mode = self.mode_combobox.get()
            
            self.status_var.set("正在分析代码结构...")
            self.log_message(f"\n▶ 开始处理: {requirement}")
            self.log_message(f"代码长度: {len(self.existing_code)}字符")
            
            if self.is_running:
                # 实际API调用
                prompt = f"""根据需求优化以下{language}代码(模式: {mode}):
                
需求: {requirement}

原代码:
{self.existing_code}

请返回优化后的完整代码，不要包含解释。"""
                
                optimized_code = self.call_deepseek_api(prompt)
                if optimized_code:
                    self.generated_code = optimized_code
                    self.log_message("\n✓ 优化完成!")
                    self.log_message(f"\n优化后代码:\n{optimized_code[:500]}...")
                    self.status_var.set("优化完成")
                else:
                    self.status_var.set("API调用失败")
            
        except Exception as e:
            self.log_message(f"\n! 处理出错: {str(e)}")
            self.status_var.set("错误发生")
        finally:
            self.is_running = False

    def call_deepseek_api(self, prompt):
        try:
            headers = {
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            }
            
            data = {
                "model": "deepseek-chat",
                "messages": [{"role": "user", "content": prompt}],
                "temperature": 0.3 if self.mode_combobox.get() == "稳定模式" else 0.7,
                "max_tokens": 4000
            }
            
            response = requests.post(self.api_url, headers=headers, json=data, timeout=120)
            response.raise_for_status()
            
            result = response.json()
            content = result["choices"][0]["message"]["content"].strip()
            
            if content.startswith("```") and content.endswith("```"):
                lines = content.split("\n")
                content = "\n".join(lines[1:-1])
            
            return content
        
        except Exception as e:
            self.log_message(f"\n! API错误: {str(e)}")
            return None

    # 辅助方法
    def force_retry(self):
        if self.existing_code:
            self.start_generation_thread()
        else:
            self.browse_existing_code()

    def stop_generation(self):
        self.is_running = False
        self.status_var.set("已停止")

    def browse_save_path(self):
        path = filedialog.askdirectory()
        if path:
            self.save_path_entry.delete(0, tk.END)
            self.save_path_entry.insert(0, path)

    def save_code(self):
        if not self.generated_code:
            messagebox.showerror("错误", "没有可保存的代码")
            return
        
        save_path = self.save_path_entry.get().strip()
        if not save_path:
            messagebox.showerror("错误", "请选择保存路径")
            return
        
        filename = simpledialog.askstring("保存代码", "请输入文件名(不含扩展名):")
        if not filename:
            return
        
        language = self.language_combobox.get().lower()
        ext_map = {
            "python": ".py", "javascript": ".js", "java": ".java",
            "c++": ".cpp", "c#": ".cs", "go": ".go", "rust": ".rs",
            "php": ".php", "ruby": ".rb", "swift": ".swift"
        }
        
        extension = ext_map.get(language, ".txt")
        filepath = os.path.join(save_path, f"{filename}{extension}")
        
        try:
            with open(filepath, "w", encoding="utf-8") as f:
                f.write(self.generated_code)
            self.save_status_label.config(text=f"保存成功: {os.path.basename(filepath)}")
            self.log_message(f"\n✓ 代码已保存到: {filepath}")
        except Exception as e:
            self.save_status_label.config(text=f"保存失败: {str(e)}")
            self.log_message(f"\n! 保存错误: {str(e)}")

    def run_saved_code(self):
        save_path = self.save_path_entry.get().strip()
        if not save_path:
            messagebox.showerror("错误", "请选择保存路径")
            return
        
        filename = simpledialog.askstring("运行代码", "请输入文件名(不含扩展名):")
        if not filename:
            return
        
        language = self.language_combobox.get().lower()
        ext_map = {
            "python": ".py", "javascript": ".js", "java": ".java",
            "c++": ".cpp", "c#": ".cs", "go": ".go", "rust": ".rs",
            "php": ".php", "ruby": ".rb", "swift": ".swift"
        }
        
        extension = ext_map.get(language, ".txt")
        filepath = os.path.join(save_path, f"{filename}{extension}")
        
        if not os.path.exists(filepath):
            messagebox.showerror("错误", f"文件不存在: {filepath}")
            return
        
        try:
            if language == "python":
                subprocess.Popen(["python", filepath], creationflags=subprocess.CREATE_NEW_CONSOLE)
            elif language == "javascript":
                subprocess.Popen(["node", filepath], creationflags=subprocess.CREATE_NEW_CONSOLE)
            else:
                messagebox.showinfo("提示", f"请手动运行 {language} 代码: {filepath}")
            
            self.log_message(f"\n▶ 正在运行: {filepath}")
        except Exception as e:
            self.log_message(f"\n! 运行错误: {str(e)}")

    def log_message(self, message):
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.root.update()

    def load_config(self):
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, "r", encoding="utf-8") as f:
                    config = json.load(f)
                    self.api_key = config.get("api_key", "")
                    self.api_key_entry.delete(0, tk.END)
                    self.api_key_entry.insert(0, self.api_key)
                    self.save_path_entry.delete(0, tk.END)
                    self.save_path_entry.insert(0, config.get("save_path", ""))
        except Exception as e:
            self.log_message(f"\n! 配置加载错误: {str(e)}")

    def save_config(self):
        self.api_key = self.api_key_entry.get().strip()
        try:
            with open(self.config_file, "w", encoding="utf-8") as f:
                json.dump({
                    "api_key": self.api_key,
                    "save_path": self.save_path_entry.get().strip()
                }, f, ensure_ascii=False, indent=2)
            self.log_message("\n✓ 配置已保存")
        except Exception as e:
            self.log_message(f"\n! 配置保存错误: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = DeepSeekCodeGenerator(root)
    root.mainloop()